import MySQLdb
import consultasBD
from datetime import date
from datetime import datetime
import Mensaje
import Dialog2
import wx
from decimal import Decimal
import os
import Email
import sys


ROJO = (255, 145, 145, 255)
VERDE = (145, 255, 145, 255)
AZUL = (145, 145, 255, 255)
BLANCO = (255, 255, 255, 255)
AMARILLO = (254, 248, 191, 255)

def agregar_movimiento(ptc, stock_previo, stock_nuevo, operacion, sucursal, observacion = "", idcompra="", idventa="", idtransferencia=""):
    sql_movimiento = "INSERT INTO movimientos_stock (ptc, stock_previo, stock_nuevo, operacion, sucursal,observacion, idcompra, idventa, idtransferencia) VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s')" % (ptc, stock_previo, stock_nuevo, operacion,sucursal, observacion, idcompra, idventa, idtransferencia) 
            
    consultasBD.executaSinCommit(None, sql_movimiento)

def logOperaciones(texto):
    fechaHora = str(datetime.today())
    cadena  = fechaHora[:19] + " " + texto
    cadena += "\n"
    f = open("log_Operacion.txt","a")
    f.write(cadena)
    f.close()

def logBD(texto):
    fechaHora = str(datetime.today())
    cadena = fechaHora[:19] + " " + texto + "\n"
    f = open("log_BD.txt","a")
    f.write(cadena)
    f.close()

def isGrillaEmpy(grilla, cant):    
    result = True
    for x in xrange(cant):        
        valor = grilla.GetCellValue(int(x),0)
        if valor != "":
            result = False
        
    return result

def isCajaCerrada(fecha):
    '''Valida si la caja esta cerrada para una fecha dada'''
    if fecha == "":
        sql = "SELECT * FROM parametros WHERE DATEDIFF(cajacerrada, SYSDATE()) >= 0 AND sucursal = '%s'" % getSucursalActiva()
    else:    
        sql = "SELECT * FROM parametros WHERE DATEDIFF(cajacerrada, '%s') >= 0 AND sucursal = '%s'" % (fecha, getSucursalActiva())
    resultado = consultasBD.ordenCrudaResultDict(sql)
    return resultado != []

def colorear_fila(grilla, fila, color):
    '''colorea la fila en la la posicion "fila" del color "color" '''
    for i in range(grilla.GetNumberCols()):
        grilla.SetCellBackgroundColour(fila,i, color)              

def stock_sumado(ptc, sucursal, cantidad):
    '''Devuelve el stock de un ptc adicionando una cantidad'''
    sql = "SELECT stock FROM stock WHERE ptc = '%s' AND sucursal = '%s'" % (ptc, sucursal)
    result = consultasBD.ordenCrudaResultDictSinCommit(sql)
    print "stock sumado sql:"+str(sql)
    if len(result) == 0:
        return int(cantidad)
    
    return (Decimal(result['stock']) + cantidad)

def isDecimal(val):
    import decimal
    try:
        decimal.Decimal(val)    
        return True
    except:
        return False    
    
def isInt(val):
    import decimal
    try:
        int(val)    
        return True
    except:
        return False       

def secuencia(tabla, sucursal):
    '''
    Devuelve el proximo numero de la secuencia para un numero.
    Concatena la sucusal adelante para que no problemas entre las distintas
    sucursales
    '''
    sql = "SELECT * FROM secuencias WHERE tabla = '%s'" % tabla
    result = consultasBD.ordenCrudaResultDictSinCommit(sql)
    if len(result) == 0:
        sql_insert = "INSERT INTO secuencias (tabla, numero) VALUES('%s', '%s')" % (tabla, 2)
        consultasBD.executaSinCommit(None, sql_insert)
        logOperaciones("utiles.py: secuencia() %s-1" % sucursal)
        return "%s-1" % sucursal
    else:
        sql_update = "UPDATE secuencias SET numero = numero + 1 WHERE tabla = '%s'" % tabla
        consultasBD.executaSinCommit(None, sql_update)
        logOperaciones("utiles.py: secuencia() SUCURSAL "+str(sucursal)+" "+str(result['numero']))
        return "%s-%s" % (sucursal, result['numero'])

def getSucursalActiva():
    sql = "SELECT idsucursal FROM sucursales WHERE activa = 1"
    result = consultasBD.ordenCrudaResultDict(sql)
    if len(result) == 0:
        print "No hay sucursal activa en la BD"
        logOperaciones("utiles.py: getSucursalActiva() -> no hay sucursal activa en la BD")
        return "0"
    else:
        return str(result['idsucursal'])

def formatear_fecha(fecha):
    aux = str(fecha).split("/")
    return "%s/%s/%s %s" % (aux[1], aux[0], aux[2], "00:00:00")

def formatear_fecha_date(fecha):
    #return "01-07-2008 00:00:00"
    
    print "fecha ", str(fecha)
    aux = str(fecha).split(" ")[0].split("/")
    return "%s-%s-%s %s" % (aux[2], aux[0], aux[1], "00:00:00")    

def formatear_fecha_date2(fecha):
    aux = str(fecha).split(" ")[0].split("/")
    return "%s-%s-%s" % (aux[2], aux[0], aux[1])  
    
def cargar_fecha(fecha, date_picker):
    aux = str(fecha).split(" ")[0].split("-")
    
    f = wx.DateTime.Today()
    f.SetYear(int(aux[0]))
    f.SetMonth(int(aux[1]) - 1)
    f.SetDay(int(aux[2]))    
    date_picker.SetValue(f)    

def mensaje(parent, texto):
    '''Muestra un dialogo en la pantalla con un mensaje'''
    dlg = Mensaje.Mensaje(parent,texto)
    try:
        dlg.ShowModal()            
    finally:
        dlg.Destroy()                 
    return False    

def dialog2(parent, texto):
    '''Muestra una ventana donde debe Aceptarse o Cancelarse una accion'''
    dlg = Dialog2.Dialog2(parent, texto)
    opcion = False
    try:
        dlg.ShowModal()
        opcion = dlg.getSeleccion()
    finally:
        dlg.Destroy()
    return opcion

def mensaje_procesando(parent):
    ''''''
    dlg = Mensaje.Mensaje(parent,texto)
    try:
        dlg.Show()         
    finally:
        dlg.Destroy()
    return False  

#hay stock del producto que estoy buscando en esa sucursal? ...Donde hay sino?
def verificoStock(cantidad,ptc,sucursal):
    return True
#CUANDO EL STOCK SE NORMALICE Y QUEDE SIN CANTIDADES < 0, ENTONCES BORRAR LA LINEA ANTERIOR
    from decimal import Decimal
    inStock = Decimal("0.00")
    tablaSQL = "stock"
    condicion = "ptc='%s' AND sucursal=%s " % (str(ptc),str(sucursal))
    consultaSQL = "SELECT stock FROM %s WHERE %s" % (tablaSQL,condicion)
    resultado = consultasBD.ordenCrudaDict(consultaSQL)
    if len(resultado) != 1:
        return False
    inStock = Decimal(str(resultado[0]['stock']))
    if (Decimal(inStock) >= Decimal(cantidad)):
        return True
    else:
        return False

def verificoStockTalleColor(self,cantidad,codsussan,talle,color,sucursal):
    inStock=0
    tablaSQL="stock"
    ptc= buscaPTC( self, codsussan, talle, color)
    condicion="ptc='%s' AND sucursal=%s " % (str(ptc),str(sucursal))
    result = consultasBD.executaSQL(self,"stock",tablaSQL,condicion)
    for r in result:
        inStock = r[0]

        return True
    else:
        return False

def buscaPTC( self, codsussan, talle, color):
    SQL = "Select id from producto_talle_color where codsussan='%s' AND talle='%s' AND color='%s'" % (codsussan,talle,color)
    resultado = consultasBD.ordenCrudaResultDict(SQL)
    return (resultado['id'])        
            
def getfechatoday(self):
    now = date.today()
    return str(now.strftime("%d-%m-%y"))

def getfechaDiaLaboral(fecha,valor):
    #fecha es tipo datetime y devuelve ese mismo tipo de datos
    #valor es positivo o negativo, segun sume o reste dias. fecha+valor=nuevaFecha
    from datetime import timedelta
    from consultasBD import ordenCruda
    consultaSQL = "SELECT fecha FROM feriados"
    resultado = ordenCruda(consultaSQL)
    feriado = [] 
    for dia in resultado:
        feriado.append(dia[0])
    dif = timedelta(days=valor)
    fecha = fecha + dif
    while (fecha in feriado) or ((diaSemana(fecha) == 7)):
        fecha = fecha + dif
    return fecha

def sumarDiasAFecha(fecha,valor):
    #fecha es tipo datetime y devuelve ese mismo tipo de datos
    #valor es positivo o negativo, segun sume o reste dias. fecha+valor=nuevaFecha
    from datetime import timedelta
    dif = timedelta(days=valor)
    fecha = fecha + dif
    return fecha

def getfechaDiaLaboralAnterior(fecha):
    #recibe y devuelve un valor datetime
    return getfechaDiaLaboral(fecha,-1)

def getfechaDiaLaboralSiguiente(fecha):
    #recibe y devuelve un valor datetime
    return getfechaDiaLaboral(fecha,1)

def getFechaCierreTarjeta():
    sucursalActiva = getSucursalActiva()
    sentenciaSQL = "SELECT fechacierretarjeta FROM parametros WHERE sucursal = '"+sucursalActiva+"'"
    resultado = consultasBD.ordenCrudaDict(sentenciaSQL)
    return (resultado[0]['fechacierretarjeta'])

def sumarDiasLaboralesAFecha(valor):
    aux = strToDate(getfechaInverse())
    if valor == 0:
        return aux
    if valor < 0:
        multiplicador = -1
    else:
        multiplicador = 1
    valor = abs(valor)
    for i in xrange(valor):
        aux = getfechaDiaLaboral(aux,multiplicador)
    return aux

def getfecha15LaboralesAtras():
    aux = strToDate(getfechaInverse())
    for i in xrange(15):
        aux = getfechaDiaLaboral(aux,-1)
    return aux

def diaSemana(fecha):
    #1 Lunes, 2 Martes, 3, Miercoles, 4 Jueves, 5, Viernes, 6 Sabado, 7 Domingo
    return fecha.isoweekday()

def isDiaNoLaboral(fecha):
    from consultasBD import ordenCruda
    consultaSQL = "SELECT fecha FROM feriados"
    resultado = ordenCruda(consultaSQL)
    feriado = []
    for dia in resultado:
        feriado.append(dia[0])
    if (fecha in feriado) or ((diaSemana(fecha) == 7)):
        return True
    else:
        return False

def isDiaLaboral(fecha):
    return not isDiaNoLaboral(fecha)
    
def getfechaInverse():
    now = date.today()
    return now.strftime("%Y-%m-%d")

def getfecha():
    now = date.today()
    return str(now.strftime("%d-%m-%Y"))
        
def getfechaInverseTime():
    import time
    return time.strftime("%Y-%m-%d %H:%M-%S")

def convertirFecha(fecha):
    return fecha.strftime("%d-%m-%Y")
            
def getDaysExtreme():
    from calendar import monthrange
    from datetime import datetime
    from time import strptime
    now = date.today()
    mes = int(now.strftime("%m"))
    anio = int(now.strftime("%Y"))
    primerDia = '01'+str(now.strftime("-%m-%Y"))
    ultimoDia = str(monthrange(int(anio),int(mes))[1])+str(now.strftime("-%m-%Y"))
    print primerDia
    primerDia = datetime(*strptime(primerDia, "%d-%m-%Y")[0:5])
    print primerDia
    ultimoDia = datetime(*strptime(ultimoDia, "%d-%m-%Y")[0:5])
    return [primerDia, ultimoDia]
    
def isFechaDelMesActual(fecha):
    #fecha debe venir como datetime y en formato Y-m-d
    return getfechaInverse()[:7] == str(fecha)[:7]

def isFechaDelMesAnterior(fecha):
    #fecha debe venir como datetime y en formato Y-m-d
    return getfechaInverse()[:7] > str(fecha)[:7]

def strToDate(fecha):
    #recibe un string en formato Y-m-d y devuelve un datetime.date de forma %Y-%m-%d
    return date(*map(int,fecha.split("-")))

def invertirFecha(fecha):
    #recibe un string en formato d-m-Y y lo devuelve como Y-m-d
    return fecha[-4:]+"-"+fecha[3:5]+"-"+fecha[:2]

def getFechaLaboralMesSiguiente(fecha):
    from datetime import timedelta
    dif = timedelta(days=30)
    fecha = fecha + dif
    if isDiaNoLaboral(fecha):
        return getfechaDiaLaboralSiguiente(fecha)
    else:
        return fecha
    
def cambiaFormatoFecha(self,fecha):
    dia = fecha.GetDay()
    if dia < 10:
        dia = "0"+str(dia)
        
    mes = fecha.GetMonth() + 1
    if mes < 10:
        mes = "0"+str(mes)
        
    anio = (str(fecha.GetYear()))[2:]
    
    return "%s-%s-%s" % (dia,mes,anio)

def obtenerNombreCliente(idcliente):
    sucursalActiva = getSucursalActiva()
    sentenciaSQL = "SELECT nombre FROM cliente WHERE idcliente = '"+idcliente+"'"
    resultado = consultasBD.ordenCrudaDict(sentenciaSQL)
    return (resultado[0]['nombre'])

def getFechaVencimientoTarjeta():
    sucursalActiva = getSucursalActiva()
    sentenciaSQL = "SELECT fechavencimientotarjeta FROM parametros WHERE sucursal = '"+sucursalActiva+"'"
    resultado = consultasBD.ordenCrudaDict(sentenciaSQL)
    return (resultado[0]['fechavencimientotarjeta'])
    
def obtenerNumeroRecibo(sucursal):
    #buscamos el ultimo nrorecibo generado, guardado en parametros
    sentenciaSQL = "select ultimonrorecibo from parametros where sucursal = "+sucursal
    resultado = consultasBD.ordenCrudaDict(sentenciaSQL)
    return ( int(resultado[0]['ultimonrorecibo']) + 1 )

def obtenerNumeroVentaA(sucursal):
    import fiscal
    retorna = fiscal.getUltimoA()
    if retorna < 0:
        texto  = "Hay problemas con la impresora fiscal (A)\nNo pudo obtenerse un nro. ticket A"
        mensaje(None,texto)
        #buscamos el ultimo nroVenta1 generado, guardado en parametros
        sentenciaSQL = "select ultimonroventaA from parametros where sucursal = "+sucursal
        resultado = consultasBD.ordenCrudaDict(sentenciaSQL)
        return ( long(resultado[0]['ultimonroventaA']) + 1 )
    else:
        return retorna + 1

def obtenerNumeroVentaB(sucursal):
    import fiscal
    retorna = fiscal.getUltimoBC()
    if retorna < 0:
        texto  = "Hay problemas con la impresora fiscal (B)\nNo pudo obtenerse un nro. ticket BC"
        mensaje(None,texto)
        #buscamos el ultimo nroVenta1 generado, guardado en parametros
        sentenciaSQL = "select ultimonroventaB from parametros where sucursal = "+sucursal
        resultado = consultasBD.ordenCrudaDict(sentenciaSQL)
        return ( long(resultado[0]['ultimonroventaB']) + 1 )
    else:
        return retorna + 1
    
def obtenerNumeroVenta2(sucursal):
    #buscamos el ultimo nroVenta2 generado, guardado en parametros
    sentenciaSQL = "select ultimonroventa2 from parametros where sucursal = "+sucursal
    resultado = consultasBD.ordenCrudaDict(sentenciaSQL)
    return ( long(resultado[0]['ultimonroventa2']) + 1 )

def obtenerNumeroConsignacion(sucursal):
    #buscamos el ultimo de consignacion generado, guardado en parametros
    sentenciaSQL = "select ultimoidconsignacion from parametros where sucursal = "+sucursal
    resultado = consultasBD.ordenCrudaDict(sentenciaSQL)
    return ( int(resultado[0]['ultimoidconsignacion']) + 1 )

def guardarNumeroRecibo(nrorecibo, sucursal):
    #guardar el nrorecibo generado
    tablaSQL = "parametros"
    camposSQL = "ultimonrorecibo = "+str(nrorecibo)
    condicionSQL = "sucursal = "+sucursal
    consultasBD.executaUpdateSQL(None,tablaSQL,camposSQL,condicionSQL)
    
def guardarNumeroVentaA(nroventa1, sucursal):
    #guardar el nroventa1 generado
    tablaSQL = "parametros"
    camposSQL = "ultimonroventaA = "+str(nroventa1)
    condicionSQL = "sucursal = "+sucursal
    consultasBD.executaUpdateSQL(None,tablaSQL,camposSQL,condicionSQL)

def guardarNumeroVentaB(nroventa1, sucursal):
    #guardar el nroventa1 generado
    tablaSQL = "parametros"
    camposSQL = "ultimonroventaB = "+str(nroventa1)
    condicionSQL = "sucursal = "+sucursal
    consultasBD.executaUpdateSQL(None,tablaSQL,camposSQL,condicionSQL)

def guardarNumeroVenta2(nroventa2, sucursal):
    #guardar el nroventa2 generado
    tablaSQL = "parametros"
    camposSQL = "ultimonroventa2 = "+str(nroventa2)
    condicionSQL = "sucursal = "+sucursal
    consultasBD.executaUpdateSQL(None,tablaSQL,camposSQL,condicionSQL)

def guardarNumeroConsignacion(idconsignacion, sucursal):
    #guardar el nroventa2 generado
    tablaSQL = "parametros"
    camposSQL = "ultimoidconsignacion = "+str(idconsignacion)
    condicionSQL = "sucursal = "+sucursal
    consultasBD.executaUpdateSQL(None,tablaSQL,camposSQL,condicionSQL)

def obtenerRecargo(idrecargo):
    sentenciaSQL = "SELECT * FROM vtas_recargos WHERE idrecargo = '"+idrecargo+"'"
    resultado = consultasBD.ordenCrudaDict(sentenciaSQL)
    return resultado[0]

#*******************************************************************************

def aLetras(numero):
    #recibe un valor tipo Decimal y devuelve un string
    from decimal import Decimal

    numeros = {0:"CERO",2:"DOS",3:"TRES",4:"CUATRO",5:"CINCO",6:"SEIS",7:"SIETE",8:"OCHO",9:"NUEVE",
                10:"DIEZ",11:"ONCE",12:"DOCE",13:"TRECE",14:"CATORCE",15:"QUINCE",16:"DIECISEIS",17:"DIECISIETE",
                18:"DIECIOCHO",19:"DIECINUEVE",20:"VEINTE",30:"TREINTA",
                40:"CUARENTA",50:"CINCUENTA",60:"SESENTA",70:"SETENTA",80:"OCHENTA",90:"NOVENTA",100:"CIEN",
                500:"QUINIENTOS ",700:"SETECIENTOS ",900:"NOVECIENTOS "}

    if abs(numero) > 999999999.99 : #mil millones, esta funcion procesa el rango [-999.999.999,99; 999.999.999,99]
        return "0"
    elif numero < 0:
        cadena = "MENOS "
    else:
        cadena = ""

    #separo el numero entregado entre parte entera y sus decimales (tomando solo 2 y redondeando para arriba)
    entero = int(abs(numero))
    decimales = int((round(abs(numero),2)+0.001) * 100) % 100
    #la parte entera es separada en grupos de tres digitos
    grupo1 = int(entero / 1000000)
    grupo2 = int((int(entero) - int(grupo1)*1000000)/1000)
    grupo3 = int(entero % 1000)

    lista = [grupo1,grupo2,grupo3,decimales]

    if (grupo1+grupo2+grupo3) == 0:
        cadena += numeros[0]

    for i in xrange(4):
        unidad = lista[i] % 10
        decena = lista[i] % 100
        centena = (lista[i] / 100) % 10
        subcadena = ""

        numeros[1] = "UNO" if i == 2 else "UN"
        
        if i == 0: #grupo 1: el de los millones
            if decena == 1: 
                subcadena = " MILLON "
            elif lista[i] > 1: 
                subcadena = " MILLONES "
            else: #aqui se entra si lista[i] == 0 y en ese caso, no hay nada que procesar
                continue #se sigue con la siguiente iteracion del bucle
        elif i == 1: #grupo2: el de los miles
            if lista[i] == 1:
                cadena += " MIL "
                continue #se pasa a la siguiente iteracion
            elif lista[i] > 1:
                subcadena = " MIL "
            else: #aqui se entra si lista[i] == 0 y en ese caso, no hay nada que procesar
                continue #se sigue con la siguiente iteracion del bucle
        elif i == 3 and lista[i] != 0: #grupo4: el de los centavos (decimales)
            cadena += " CON "
            subcadena = " CENTAVOS"

        if centena != 0:
            if centena == 1 and (unidad + decena) == 0:
                cadena += numeros[100]
                continue
            elif centena == 1:
                cadena += "CIENTO "
            elif centena == 5:
                cadena += numeros[500]
            elif centena == 7:
                cadena += numeros[700]
            elif centena == 9:
                cadena += numeros[900]
            else:
                cadena += numeros[centena]+"CIENTOS "

        if decena != 0:
            if decena < 21:
                cadena += numeros[decena]
            elif decena < 30:
                cadena += "VENTI"+numeros[unidad]
            else:
                cadena += numeros[(decena/10)*10]
                if unidad > 0:
                    cadena += " Y "+numeros[unidad]

        cadena += subcadena

    return cadena

#*******************************************************************************

#toma una cadena de texto y la separa en cadenas de longitud igual o menor a "size"
def splitear(text, size = 10):
    if len(text) > size:
        list = text.split()
        text = []
        string = ""
        for word in list:
            if len(string)+len(word)+1 <= size:
                string += word + " "
            else:
                text.append(string.strip())
                string = word + " "
        text.append(string.strip())
    return text

#*******************************************************************************
#OBTENIDA DE PYAR
#def validar_cuit(cuit)

def validarCuit(cuit):
    # validaciones minimas
    if len(cuit) != 11:
        return False

    base = [5,4,3,2,7,6,5,4,3,2]    

    # calculo el digito verificador:
    aux = 0
    for i in xrange(10):
        aux += int(cuit[i])*base[i]
    
    aux = 11-(aux-(int(aux / 11)*11))
    
    if aux==11:
        aux = 0
    if aux==10:
        aux = 9
    
    return aux == int(cuit[10])

#LARGA LA IMPRESION EN UN HTML
def reporte_html(self,datos, columnas,esZ = "0"):
        html = open('reporte.html', 'r').read()
        titulo = "Caja Diaria"
        cadena_reemplazo = '<table border="1" cellpadding="0" cellspacing="0"><caption>%s</caption><thead>%s</thead><tbody align="left">%s</tbody></table>'

        nombre_columnas = '<tr>'
        for nombre in columnas:
            nombre_columnas += '<td><strong> %s </strong></td>' % nombre
        nombre_columnas += '</tr>'

        contenido = ''
        
        print datos
        print columnas
        for fila in datos:
            contenido += '<tr>'
            for columna in fila:
                contenido += '<td> %s </td>' % columna
            contenido += '</tr>'

        
        cadena_reemplazo = cadena_reemplazo % (titulo, nombre_columnas, contenido)
        html = html.replace('{ % reemplazar % }', cadena_reemplazo)
        archivo_salida = open('reporte_html.html', 'w')
        archivo_salida.write(html)
        archivo_salida.close()
        print html
        
        
        #mando el email.
        os.system("c:\explorer.lnk")
        
        
        # si hace el cierre Z...envio el cierre por email.
        if esZ=="1" :
            try: 
                serverName ="smtp.datamarkets.com.ar"
                host= "smtp.datamarkets.com.ar"
                user="a77142"
                password="a77142"
                email_from="erpsussan@gmail.com"
                email_destinatario="erpsussan@gmail.com"
                subject="Cierre Caja: "+str(self.padre.fecha)
                html_path= "reporte_html.html"
                image_path= "logo_sussan_simple.png"
                email = Email.Email(user, password, host, 25, email_from, subject,html_path, image_path)
                msg = email.create_msg(email_destinatario)
                try:
                    email.send_email(email_from, email_destinatario, msg)
                finally:
                    pass
                    
            
            finally:
                pass
            
